package com.cloud.system.project.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloud.common.core.asserts.ApiAssert;
import com.cloud.common.core.cons.StatusCons;
import com.cloud.common.core.enums.ErrorCodeEnum;
import com.cloud.common.core.utils.TreeUtils;
import com.cloud.system.project.cons.MenuTypeCons;
import com.cloud.system.project.mapper.MenuMapper;
import com.cloud.system.project.model.dto.MenuDTO;
import com.cloud.system.project.model.dto.MenuTreeDTO;
import com.cloud.system.project.model.entity.Menu;
import com.cloud.system.project.model.entity.RoleMenu;
import com.cloud.system.project.service.IMenuService;
import com.cloud.system.project.service.IRoleMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author Sam
 * @since 2021-04-13
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Autowired
    private IRoleMenuService roleMenuService;

    @Override
    public List<MenuTreeDTO> getTreeList(Integer status) {
        List<MenuTreeDTO> treeSource = this.list(Wrappers.<Menu>lambdaQuery()
                .eq(Objects.nonNull(status), Menu::getStatus, status)
                .orderByAsc(Menu::getOrderNum))
                .stream().map(e -> e.convert(MenuTreeDTO.class)).collect(Collectors.toList());
        List<MenuTreeDTO> treeList = treeSource.stream().filter(e -> !(Objects.nonNull(e.getPid()) && !"0".equals(e.getPid())))
                .map(e -> TreeUtils.findChildren(e, treeSource)).collect(Collectors.toList());
        return treeList;
    }

    @Override
    public List<MenuTreeDTO> getTreeAllPermMenus(Integer status) {
        List<MenuTreeDTO> menus = this.list(Wrappers.<Menu>lambdaQuery()
                .eq(Objects.nonNull(status), Menu::getStatus, status)
                .orderByAsc(Menu::getOrderNum))
                .stream().map(e -> e.convert(MenuTreeDTO.class)).collect(Collectors.toList());
        return menus.stream().filter(e -> !parentIdNotNull(e.getPid())).map(e -> TreeUtils.findChildren(e, menus)).collect(Collectors.toList());
    }

    @Override
    public List<MenuTreeDTO> getTreeUserPermMenus(String uid) {
        List<MenuTreeDTO> menus = baseMapper.getUserPermMenus(uid, StatusCons.NORMAL, Arrays.asList(MenuTypeCons.CATALOG, MenuTypeCons.MENU));
        return menus.stream().filter(e -> !parentIdNotNull(e.getPid())).map(e -> TreeUtils.findChildren(e, menus)).collect(Collectors.toList());
    }

    /**
     * 父ID不为0并且不为空
     *
     * @param parentId
     * @return
     */
    private boolean parentIdNotNull(String parentId) {
        return Objects.nonNull(parentId) && !"0".equals(parentId);
    }

    @Override
    public List<MenuTreeDTO> getUserPermMenus(String uid) {
        List<MenuTreeDTO> menus = getUserPermMenus(uid, Arrays.asList(MenuTypeCons.CATALOG, MenuTypeCons.MENU));
        return menus;
    }

    @Override
    public List<MenuTreeDTO> getUserPermMenus(String uid, List<Integer> types) {
        List<MenuTreeDTO> menus = baseMapper.getUserPermMenus(uid, StatusCons.NORMAL, types);
        return menus;
    }

    @Override
    public List<MenuDTO> getListByRoleId(String roleId) {
        return baseMapper.getListByRoleId(roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delMenu(String menuId) {
        int count = this.count(Wrappers.<Menu>lambdaQuery().eq(Menu::getPid, menuId));
        ApiAssert.isFalse(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("存在下级菜单,不允许删除"), count > 0);
        Menu menu = new Menu();
        menu.setId(menuId);
        menu.setStatus(StatusCons.DISABLE);
        ApiAssert.isTrue(ErrorCodeEnum.BAD_DELETE_FAILURE, this.updateById(menu));
        //删除对应角色关系
        roleMenuService.remove(Wrappers.<RoleMenu>lambdaQuery().eq(RoleMenu::getMenuId, menuId));
    }

}
